import unittest

from tinydb.storage.slotted_page import *


class TestSlottedPage(unittest.TestCase):
    def test_page_header(self):
        page_header = PageHeader()
        page_header.flags = 0xff
        page_header.reserved = 1
        page_header.lsn = 123

        buff = page_header.serialize()

        page_header2 = PageHeader.deserialize(buff)
        self.assertEqual(page_header, page_header2)

    def test_slot_page(self):
        page = Page()
        sid = page.insert(b'hello')
        page.set_header(1)

        self.assertEqual(sid, 0)
        self.assertEqual(page.select(sid), b'hello')
        sid = page.insert(b'world')
        page.set_header(2)

        self.assertEqual(page.select(sid), b'world')
        
        page.delete(sid)
        page.set_header(3)

        self.assertEqual(page.select(sid), b'')

        # 足够空间原地插入
        new_sid = page.update(0, b'a')
        page.set_header(4)

        self.assertEqual(new_sid, 0)
        self.assertEqual(page.select(new_sid), b'a')

        # 不够空间，需要扩容
        new_sid = page.update(0, b'a')
        page.set_header(5)

        self.assertEqual(new_sid, 0)
        self.assertEqual(page.select(new_sid), b'a')

        sid = page.insert(b'b')
        page.set_header(6)

        self.assertEqual(page.select(sid), b'b')
        # 更新的新值很长
        new_sid = page.update(sid, b'xxxxxxxxxxxxxxxxxxxxxxx')
        page.set_header(7)
        
        self.assertTrue(new_sid > sid)
        self.assertEqual(page.select(sid), b'')
        self.assertEqual(page.select(new_sid), b'xxxxxxxxxxxxxxxxxxxxxxx')

        records = []
        print()
        for sid in range(0, len(page.solt_directory)):
            print(sid, page.select(sid))
            records.append((sid, page.select(sid)))

        buff = page.serialize()
        page2 = Page.deserialize(buff)
        records2 = []
        for sid in range(0, len(page2.solt_directory)):
            records2.append((sid, page2.select(sid)))

        self.assertEqual(records, records2)


if __name__ == '__main__':
    unittest.main()
